// linux 系统下包含优雅退出和平滑重启功能
// 平滑重启核心实现介绍：https://grisha.org/blog/2014/06/03/graceful-restart-in-golang/
// +build linux

package app

import (
	"context"
	"fmt"
	"gitee.com/zhucheer/orange/cfg"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"syscall"
)

func init() {
	// 注册平滑重启参数
	cfg.SetBoolFlag("grace", false, "graceful restart app flag")
}

// listenShutDownSign 监听退出信号
func listenShutDownSign(ctx context.Context, orangeSrv *OrangeServer) {
	exitSig := []os.Signal{
		syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGUSR1,
	}

	appsign := make(chan os.Signal, 1)
	signal.Notify(appsign, exitSig...)

	select {
	case signItem := <-appsign:
		shutdownLinuxDo(ctx, orangeSrv, signItem)
	}
	signal.Stop(appsign)

	// http服务关闭后等待业务处理完成后关闭应用
	exitWaitHandler.wg.Wait()
}

// shutdownLinuxDo
func shutdownLinuxDo(ctx context.Context, orangeSrv *OrangeServer, signType os.Signal) {
	fmt.Println(fmt.Sprintf("[ORANGE] \033[0;33m shutdown sign:%v \033[0m ", signType.String()))
	switch signType {
	case syscall.SIGUSR1:
		fmt.Println("[ORANGE] \033[0;33m app grace reload \033[0m ")
		httpListener := orangeSrv.GetListener()
		forkSocket(httpListener)
	default:
		fmt.Println("[ORANGE] \033[0;33m shutdown do \033[0m ")
	}
	shutdownDo(ctx, orangeSrv)
}

func forkSocket(tcpListener *net.TCPListener) error {
	f, err := tcpListener.File()
	if err != nil {
		return err
	}

	args := []string{"-grace"}
	for k, item := range os.Args {
		if k == 0 {
			continue
		}
		args = append(args, item)
	}

	cmd := exec.Command(os.Args[0], args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	// put socket FD at the first entry
	cmd.ExtraFiles = []*os.File{f}
	return cmd.Start()
}
